package com.lxl.xm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lxl.xm.common.DailyEarning;
import com.lxl.xm.mapper.RevenueMapper;
import com.lxl.xm.model.entity.AdCampaign;
import com.lxl.xm.model.entity.Revenue;
import com.lxl.xm.model.enums.AdTypeEnum;
import com.lxl.xm.model.vo.RevenueVO;
import com.lxl.xm.service.RevenueService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class RevenueServiceImpl extends ServiceImpl<RevenueMapper, Revenue> implements RevenueService {
    private static final double DISCOUNT_THREE_MONTHS = 0.95;
    private static final double DISCOUNT_SIX_MONTHS = 0.90;
    @Autowired
    private IService<AdCampaign> adCampaignIService;
    @Lazy
    @Resource
    private IService<Revenue> revenueIService;

    @Override
    public double calculatePlacementRevenue(AdTypeEnum adTypeEnum, int duration) {
        double dailyRate = getDailyRateByAdType(adTypeEnum);
        double baseRevenue = dailyRate*duration;
        return calculateDiscountedRevenue(baseRevenue,duration);
    }

    private double getDailyRateByAdType(AdTypeEnum adTypeEnum) {
        switch (adTypeEnum){
            case BANNER:
                return 50.0;
            case VIDEO:
                return 100.0;
            case INTERACTIVE:
                return 150.0;
            default:
                return 0.0;
        }
    }

    @Override
    public double calculateDiscountedRevenue(double baseRevenue, int duration) {
        if(duration>=180){
            return baseRevenue*DISCOUNT_SIX_MONTHS;
        }else if(duration>=90){
            return baseRevenue*DISCOUNT_THREE_MONTHS;
        }else {
            return baseRevenue;
        }
    }

    @Override
    public double calculatePerformanceRevenue(long adCampaignId, double cpm, double cpc) {
        int impressions = getImpreesionsFromDataBase(adCampaignId);
        int clicks = getClicksFromDataBase(adCampaignId);
        double revenueFromImpressions = (impressions/1000.0)*cpm;
        double revenueFromClicks = clicks*cpc;
        return revenueFromClicks+revenueFromImpressions;
    }

    private int getClicksFromDataBase(long adCampaignId) {
        QueryWrapper<AdCampaign> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", adCampaignId).eq("is_deleted", 0);
        AdCampaign adCampaign = adCampaignIService.getOne(queryWrapper.select("clicks"));
        return adCampaign != null ? adCampaign.getClicks() : 0;
    }

    private int getImpreesionsFromDataBase(long adCampaignId) {
        QueryWrapper<AdCampaign> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", adCampaignId).eq("is_deleted", 0);
        AdCampaign adCampaign = adCampaignIService.getOne(queryWrapper.select("impressions"));
        return adCampaign != null ? adCampaign.getImpressions() : 0;
    }

//    @Override
//    public List<DailyEarning> getRevenueDataOfLastSevenDays() {
//        List<Revenue> revenueList = new ArrayList<>();
//        LocalDate today = LocalDate.now();
//        for(int i = 6; i >= 0; i--){
//            LocalDate date = today.minusDays(i);
//            QueryWrapper<AdCampaign>queryWrapper = new QueryWrapper<>();
//            queryWrapper.between("create_time",date.atStartOfDay(),date.plusDays(1).atStartOfDay());
//            Long clicks = adCampaignMapper.selectCount(queryWrapper);
//            double revenue = clicks/100.0;
//            revenueList.add(new Revenue(date,revenue));
//        }
//        return revenueList;
//        LocalDate sevenDayAgo = LocalDate.now().minusDays(7);
//        QueryWrapper<DailyEarning> queryWrapper = new QueryWrapper<>();
//        queryWrapper.ge("date",sevenDayAgo);
//        queryWrapper.orderByAsc("date");
//        List<DailyEarning>revenueList = revenueIService.list(queryWrapper);
//        return revenueList.stream()
//                .map(revenue -> new DailyEarning(revenue.getDate(), (long) revenue.getEarnings())).
//                collect(Collectors.toList());
//    }
    @Override
    public boolean createRevenue(Revenue revenue) {
        return save(revenue);
    }

    @Override
    public Revenue getRevenueById(Long id) {
        return getById(id);
    }

    @Override
    public boolean updateRevenue(Revenue revenue) {
        return updateById(revenue);
    }

    @Override
    public boolean deleteRevenue(Long id) {
        return removeById(id);
    }

    @Override
    public Revenue createOrUpdateRevenue(RevenueVO revenueVO) {
        revenueVO.calculateTotalEarnings(this);
        Revenue revenue = new Revenue();
        revenue.setAdCampaignId(revenueVO.getAdCampaignId());
        revenue.setEarnings(revenueVO.getEarnings());
        revenue.setDate(LocalDate.now());
        saveOrUpdate(revenue);
        return revenue;
    }

}
